package edu.hawaii.myisern.model;

import static org.junit.Assert.assertEquals;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import edu.hawaii.myisern.collaborations.jaxb.CollaboratingOrganizations;
import edu.hawaii.myisern.collaborations.jaxb.Collaboration;
import edu.hawaii.myisern.collaborations.jaxb.Years;
import edu.hawaii.myisern.organizations.jaxb.Organization;
import edu.hawaii.myisern.researchers.jaxb.Researcher;

/**
 * Class to test the XmlSemanticChecker class.
 * 
 * @author Andrew Wong, Laura Matsuo
 *
 */
public class TestXmlSemanticChecker {
  String afterMsg = "Number of removed entries should be 0 afterwards";
  
  List<Organization> orgList;
  List<Collaboration> collList;
  List<Researcher> resList;
  
  /**
   * Sets up lists that are used in many of the unit tests.
   */
  void setUpLists() {
    orgList = new ArrayList<Organization>();
    resList = new ArrayList<Researcher>();
    collList = new ArrayList<Collaboration>();
    
    Organization org1 = new Organization();
    Organization org2 = new Organization();
    Researcher res1 = new Researcher();
    Researcher res2 = new Researcher();
    Collaboration coll1 = new Collaboration();
    Collaboration coll2 = new Collaboration();

    String foo = "foo";
    
    org1.setName(foo);
    org2.setName(foo);
    res1.setName(foo);
    res2.setName(foo);
    coll1.setName(foo);
    coll2.setName(foo);
    
    orgList.add(org1);
    orgList.add(org2);
    resList.add(res1);
    resList.add(res2);
    collList.add(coll1);
    collList.add(coll2);
  }
  
  /**
   *  Test case where two or more items have the same UniqueID.
   */
  @Test
  public void testDuplicateResearchers() {
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    setUpLists();

    checker.setMode(false);
    checker.setResearcherList(this.resList);
    
    assertEquals("Number of removed entries should be 1", 1,
        checker.checkResearchers());

    assertEquals(afterMsg,
        0, checker.checkResearchers());
    
  }

  /**
   *  Test case where two or more items have the same UniqueID.
   */
  @Test
  public void testDuplicateOrganizations() {
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    this.setUpLists();
        
    checker.setMode(false);
    checker.setOrganizationList(this.orgList);
    
    assertEquals("Number of removed entries should be 1", 1,
        checker.checkOrganizations());

    assertEquals(afterMsg,
        0, checker.checkOrganizations());
    
  }

  /**
   *  Test case where two or more items have the same UniqueID.
   */
  @Test
  public void testDuplicateCollaborations() {
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    setUpLists();
    
    checker.setMode(false);
    checker.setCollaborationList(this.collList);
    
    assertEquals("Number of removed entries should be 1", 1,
        checker.checkCollaborations());

    assertEquals(afterMsg,
        0, checker.checkCollaborations());
    
  }
  
  /**
   * Check for unique IDs among all lists.
   */
  @Test
  public void testDuplicateEverything() {
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    setUpLists();
    
    checker.setMode(false);
    checker.setCollaborationList(this.collList);
    checker.setResearcherList(this.resList);
    checker.setOrganizationList(this.orgList);
    
    assertEquals("Number of removed entries should be 5", 5,
        checker.checkAll());

    assertEquals(afterMsg,
        0, checker.checkAll());
    
  }

  /**
   * Test to check year range.
   */
  @Test
  public void testInvalidYears() {
    List<Collaboration> c = new ArrayList<Collaboration>();
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    Collaboration item = new Collaboration();
    BigInteger oldYear = new BigInteger("1900");
    BigInteger newYear = new BigInteger("10000");
    BigInteger validYear = new BigInteger("2000");
    
    item.setName("test collaboration");
    Years years = new Years();
    years.getYear().add(oldYear);
    item.setYears(years);
    c.add(item);
    checker.setCollaborationList(c);
    
    assertEquals("item should be invalid due to small year", checker.checkCollaborations(), 1);
    
    c.clear();
    years.getYear().clear();
    years.getYear().add(newYear);
    item.setYears(years);
    c.add(item);
    checker.setCollaborationList(c);
    
    assertEquals("item should be invalid due to large year", checker.checkCollaborations(), 1);
    
    c.clear();
    years.getYear().clear();
    years.getYear().add(validYear);
    item.setYears(years);
    c.add(item);
    checker.setCollaborationList(c);
    
    assertEquals("item should be valid", checker.checkCollaborations(), 0);
  }
  
  /**
   * Test to ensure items have valid names.
   */
  @Test
  public void testNames() {
    List<Researcher> r = new ArrayList<Researcher>();
    Researcher item = new Researcher();
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    item.setName(null);
    r.add(item);
    checker.setResearcherList(r);
    
    assertEquals("null name should not be valid", 1, checker.checkResearchers());
    
    r.clear();
    item.setName("");
    r.add(item);
    checker.setResearcherList(r);
    
    assertEquals("empty string name should not be valid", 1, checker.checkResearchers());
  }

  /**
   * Tests links in each object type.
   */
  @Test
  public void testValidLinks() {
    XmlSemanticChecker checker = new XmlSemanticChecker();
    
    orgList = new ArrayList<Organization>();
    resList = new ArrayList<Researcher>();
    collList = new ArrayList<Collaboration>();
    
    Organization org = new Organization();
    Researcher res = new Researcher();
    Collaboration coll = new Collaboration();
    
    CollaboratingOrganizations collOrgList = new CollaboratingOrganizations();
    collOrgList.getCollaboratingOrganization().add("invalidOrganization");
    
    org.setName("org");
    res.setName("res");
    coll.setName("coll");
    org.setContact("invalidResearcher");
    res.setOrganization("invalidOrganization");
    coll.setCollaboratingOrganizations(collOrgList);
    
    orgList.add(org);
    resList.add(res);
    collList.add(coll);
    
    checker.setMode(false);
    checker.setCollaborationList(collList);
    checker.setResearcherList(resList);
    checker.setOrganizationList(orgList);
    
    assertEquals("all three should be invalid", 3, checker.checkAll());
    
    org.setContact("coll");
    orgList.clear();
    orgList.add(org);
    checker.setCollaborationList(collList);
    checker.setResearcherList(resList);
    checker.setOrganizationList(orgList);
    assertEquals("all three should still be invalid", 3, checker.checkAll());
    
  }
}
